#pragma once
#include <unordered_map>
#include <google/protobuf/service.h>
#include "tinyrpc/net/tcpserver.h"
#include "../redis/RedisRegister.h"
#include "tinyrpc/base/conf/config.h"
#include "tinyrpc/base/codec/lengthCodec.h"
#include "rpcconnection.h"
#include "tinyrpc/net/coroutine_sync.h"

namespace TinyRPC{
struct ServiceInfo{
    google::protobuf::Service* m_service;
    std::unordered_map<std::string, const google::protobuf::MethodDescriptor*> m_methodMap;
};


class TinyRPCServer : public TcpServer{
public:
    TinyRPCServer(int threadNum = 0) : TcpServer(&m_eventLoop, threadNum){
        m_codec = new LengthCodec();
        m_quit = false;
    }
    void init(const std::string &filePath);
    void registService(google::protobuf::Service * service);
    void start();
    ~TinyRPCServer();
private:
    // 处理连接请求
    void co_accept();
    // 处理一个客户端连接里面的一次RPC请求
    void co_handleOneRequest(SocketChannelPtr socketChannel, std::string rpc_str);
    // 处理一个客户端连接
    void co_handleRPCConnection(SocketChannelPtr socketChannel);
    void sendRpcResponse(SocketChannelPtr socketChannel, uint32_t msg_no, int code, google::protobuf::Message * response);   //, uint32_t msg_no

    // 清除不活跃的连接
    void co_clearInActiveConn();
private:
    // service相关
    Config m_config;
    std::unordered_map<std::string, ServiceInfo> m_serviceMap;
    RedisRegister m_register;

    EventLoop m_eventLoop;
    INetAddress m_serverAddress;

    // 解码器
    AbstractCodec* m_codec;

    // 记录所有的连接信息
    std::unordered_map<int, RPCConnectionPtr> m_conns;
    CoLock m_connLock;
    bool m_quit;
};
}
